#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// ============= 第五课：动态内存分配 =============
// 学习malloc、calloc、realloc、free的使用

// 函数声明
void demonstrate_malloc(void);
void demonstrate_calloc(void);
void demonstrate_realloc(void);
void demonstrate_dynamic_arrays(void);
void demonstrate_memory_leaks(void);
void safe_free(void **ptr);
void print_memory_content(void *ptr, size_t size, const char *description);

int main(void) {
    printf("=== C语言指针学习 - 第五课：动态内存分配 ===\n\n");
    
    // 1. malloc的使用
    demonstrate_malloc();
    
    // 2. calloc的使用
    demonstrate_calloc();
    
    // 3. realloc的使用
    demonstrate_realloc();
    
    // 4. 动态数组的应用
    demonstrate_dynamic_arrays();
    
    // 5. 内存泄漏的预防
    demonstrate_memory_leaks();
    
    printf("=== 第五课总结 ===\n");
    printf("1. malloc分配未初始化的内存\n");
    printf("2. calloc分配并初始化为0的内存\n");
    printf("3. realloc调整已分配内存的大小\n");
    printf("4. 每个malloc/calloc都必须对应一个free\n");
    printf("5. 释放后应将指针设为NULL\n");
    printf("6. 动态内存分配使程序更加灵活\n");
    printf("7. 内存管理是C语言的重要技能\n");
    
    return 0;
}

void demonstrate_malloc(void) {
    printf("1. malloc函数的使用：\n");
    
    // 分配单个整数的内存
    printf("   分配单个整数的内存:\n");
    int *single_int = (int*)malloc(sizeof(int));
    
    if (single_int == NULL) {
        printf("   内存分配失败！\n");
        return;
    }
    
    *single_int = 42;
    printf("   int *single_int = malloc(sizeof(int));\n");
    printf("   *single_int = 42;\n");
    printf("   值: %d, 地址: %p\n", *single_int, (void*)single_int);
    
    // 分配整数数组的内存
    printf("\n   分配整数数组的内存:\n");
    int size = 5;
    int *int_array = (int*)malloc(size * sizeof(int));
    
    if (int_array == NULL) {
        printf("   数组内存分配失败！\n");
        free(single_int);
        return;
    }
    
    // 初始化数组
    for (int i = 0; i < size; i++) {
        int_array[i] = (i + 1) * 10;
    }
    
    printf("   int *int_array = malloc(5 * sizeof(int));\n");
    printf("   数组内容: [");
    for (int i = 0; i < size; i++) {
        printf("%d", int_array[i]);
        if (i < size - 1) printf(", ");
    }
    printf("]\n");
    
    // 显示内存内容（malloc分配的内存未初始化）
    printf("\n   malloc分配的内存内容（分配前）:\n");
    int *uninitialized = (int*)malloc(3 * sizeof(int));
    if (uninitialized != NULL) {
        printf("   未初始化的内存可能包含垃圾值:\n");
        for (int i = 0; i < 3; i++) {
            printf("   uninitialized[%d] = %d\n", i, uninitialized[i]);
        }
        free(uninitialized);
    }
    
    // 释放内存
    free(single_int);
    free(int_array);
    printf("\n   内存已释放\n\n");
}

void demonstrate_calloc(void) {
    printf("2. calloc函数的使用：\n");
    
    // calloc会将内存初始化为0
    printf("   calloc会将内存初始化为0:\n");
    int size = 5;
    int *zero_array = (int*)calloc(size, sizeof(int));
    
    if (zero_array == NULL) {
        printf("   calloc内存分配失败！\n");
        return;
    }
    
    printf("   int *zero_array = calloc(5, sizeof(int));\n");
    printf("   calloc初始化后的数组内容: [");
    for (int i = 0; i < size; i++) {
        printf("%d", zero_array[i]);
        if (i < size - 1) printf(", ");
    }
    printf("]\n");
    
    // 比较malloc和calloc
    printf("\n   malloc vs calloc比较:\n");
    int *malloc_array = (int*)malloc(3 * sizeof(int));
    int *calloc_array = (int*)calloc(3, sizeof(int));
    
    if (malloc_array != NULL && calloc_array != NULL) {
        printf("   malloc分配的内存: [");
        for (int i = 0; i < 3; i++) {
            printf("%d", malloc_array[i]);
            if (i < 2) printf(", ");
        }
        printf("] (可能包含垃圾值)\n");
        
        printf("   calloc分配的内存: [");
        for (int i = 0; i < 3; i++) {
            printf("%d", calloc_array[i]);
            if (i < 2) printf(", ");
        }
        printf("] (全部初始化为0)\n");
        
        free(malloc_array);
        free(calloc_array);
    }
    
    free(zero_array);
    printf("\n   内存已释放\n\n");
}

void demonstrate_realloc(void) {
    printf("3. realloc函数的使用：\n");
    
    // 初始分配
    printf("   初始分配3个整数的内存:\n");
    int *dynamic_array = (int*)malloc(3 * sizeof(int));
    if (dynamic_array == NULL) {
        printf("   初始内存分配失败！\n");
        return;
    }
    
    // 初始化
    for (int i = 0; i < 3; i++) {
        dynamic_array[i] = i + 1;
    }
    
    printf("   初始数组: [");
    for (int i = 0; i < 3; i++) {
        printf("%d", dynamic_array[i]);
        if (i < 2) printf(", ");
    }
    printf("]\n");
    
    // 扩大数组
    printf("\n   使用realloc扩大到5个整数:\n");
    int *temp = (int*)realloc(dynamic_array, 5 * sizeof(int));
    if (temp == NULL) {
        printf("   realloc失败！\n");
        free(dynamic_array);
        return;
    }
    dynamic_array = temp;
    
    // 初始化新元素
    dynamic_array[3] = 4;
    dynamic_array[4] = 5;
    
    printf("   扩大后的数组: [");
    for (int i = 0; i < 5; i++) {
        printf("%d", dynamic_array[i]);
        if (i < 4) printf(", ");
    }
    printf("]\n");
    
    // 缩小数组
    printf("\n   使用realloc缩小到2个整数:\n");
    temp = (int*)realloc(dynamic_array, 2 * sizeof(int));
    if (temp == NULL) {
        printf("   realloc缩小失败！\n");
        free(dynamic_array);
        return;
    }
    dynamic_array = temp;
    
    printf("   缩小后的数组: [");
    for (int i = 0; i < 2; i++) {
        printf("%d", dynamic_array[i]);
        if (i < 1) printf(", ");
    }
    printf("]\n");
    
    // realloc的特殊情况
    printf("\n   realloc的特殊情况:\n");
    printf("   - realloc(NULL, size) 等价于 malloc(size)\n");
    printf("   - realloc(ptr, 0) 等价于 free(ptr)\n");
    
    free(dynamic_array);
    printf("\n   内存已释放\n\n");
}

void demonstrate_dynamic_arrays(void) {
    printf("4. 动态数组的实际应用：\n");
    
    // 用户输入数组大小
    printf("   创建用户指定大小的动态数组:\n");
    int size = 6;  // 模拟用户输入
    printf("   假设用户输入大小: %d\n", size);
    
    // 动态分配数组
    double *scores = (double*)calloc(size, sizeof(double));
    if (scores == NULL) {
        printf("   动态数组分配失败！\n");
        return;
    }
    
    // 模拟用户输入数据
    double sample_scores[] = {85.5, 92.0, 78.5, 96.0, 88.5, 91.0};
    printf("   输入成绩: ");
    for (int i = 0; i < size; i++) {
        scores[i] = sample_scores[i];
        printf("%.1f ", scores[i]);
    }
    printf("\n");
    
    // 计算统计信息
    double sum = 0.0;
    double max = scores[0];
    double min = scores[0];
    
    for (int i = 0; i < size; i++) {
        sum += scores[i];
        if (scores[i] > max) max = scores[i];
        if (scores[i] < min) min = scores[i];
    }
    
    double average = sum / size;
    
    printf("   统计结果:\n");
    printf("   - 总分: %.1f\n", sum);
    printf("   - 平均分: %.1f\n", average);
    printf("   - 最高分: %.1f\n", max);
    printf("   - 最低分: %.1f\n", min);
    
    // 动态扩展数组（添加更多成绩）
    printf("\n   动态扩展数组（添加2个成绩）:\n");
    int new_size = size + 2;
    double *temp = (double*)realloc(scores, new_size * sizeof(double));
    if (temp == NULL) {
        printf("   扩展失败！\n");
        free(scores);
        return;
    }
    scores = temp;
    
    scores[size] = 87.0;
    scores[size + 1] = 93.5;
    
    printf("   扩展后的成绩: ");
    for (int i = 0; i < new_size; i++) {
        printf("%.1f ", scores[i]);
    }
    printf("\n");
    
    free(scores);
    printf("   动态数组内存已释放\n\n");
}

void demonstrate_memory_leaks(void) {
    printf("5. 内存泄漏的预防：\n");
    
    printf("   内存泄漏的常见原因:\n");
    printf("   1. 忘记调用free()\n");
    printf("   2. 重复释放同一块内存\n");
    printf("   3. 使用已释放的内存\n");
    printf("   4. 指针丢失导致无法释放\n\n");
    
    // 演示正确的内存管理
    printf("   正确的内存管理示例:\n");
    
    // 1. 分配内存
    char *buffer = (char*)malloc(100 * sizeof(char));
    if (buffer == NULL) {
        printf("   内存分配失败！\n");
        return;
    }
    printf("   ✓ 内存分配成功\n");
    
    // 2. 使用内存
    strcpy(buffer, "Hello, Dynamic Memory!");
    printf("   ✓ 内存使用: %s\n", buffer);
    
    // 3. 释放内存
    free(buffer);
    printf("   ✓ 内存已释放\n");
    
    // 4. 将指针设为NULL（防止野指针）
    buffer = NULL;
    printf("   ✓ 指针已设为NULL\n");
    
    // 演示安全的释放函数
    printf("\n   使用安全的释放函数:\n");
    char *safe_buffer = (char*)malloc(50 * sizeof(char));
    if (safe_buffer != NULL) {
        strcpy(safe_buffer, "Safe memory management");
        printf("   内容: %s\n", safe_buffer);
        
        // 使用安全释放函数
        safe_free((void**)&safe_buffer);
        printf("   ✓ 安全释放完成，指针自动设为NULL\n");
        
        // 验证指针已经是NULL
        if (safe_buffer == NULL) {
            printf("   ✓ 指针确实为NULL\n");
        }
    }
    
    printf("\n   内存管理最佳实践:\n");
    printf("   - 每个malloc/calloc都要有对应的free\n");
    printf("   - 释放后立即将指针设为NULL\n");
    printf("   - 使用前检查指针是否为NULL\n");
    printf("   - 避免重复释放\n");
    printf("   - 使用工具检测内存泄漏\n\n");
}

// 安全的释放函数
void safe_free(void **ptr) {
    if (ptr != NULL && *ptr != NULL) {
        free(*ptr);
        *ptr = NULL;
    }
}

// 打印内存内容（用于调试）
void print_memory_content(void *ptr, size_t size, const char *description) {
    if (ptr == NULL) {
        printf("   %s: NULL指针\n", description);
        return;
    }
    
    unsigned char *bytes = (unsigned char*)ptr;
    printf("   %s: ", description);
    for (size_t i = 0; i < size; i++) {
        printf("%02x ", bytes[i]);
    }
    printf("\n");
} 